package cn.zhaopin.starter.security.filter;

import cn.zhaopin.common.constant.LogConstants;
import cn.zhaopin.common.context.UserContextHolder;
import cn.zhaopin.starter.security.cache.SecurityCacheUtil;
import cn.zhaopin.starter.security.common.SecurityConstant;
import cn.zhaopin.starter.security.properties.JwtProperties;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;

/**
 * Description: api验证
 *
 * @author zuomin (myleszelic@outlook.com)
 * @date: 2021/10/12-11:24
 */
@Slf4j
public class ApiTokenAfterAuthorizationWebFilter implements WebFilter {

    private final SecurityCacheUtil securityCacheUtil;

    private final JwtProperties jwtProperties;

    public ApiTokenAfterAuthorizationWebFilter(SecurityCacheUtil securityCacheUtil, JwtProperties jwtProperties) {
        this.securityCacheUtil = securityCacheUtil;
        this.jwtProperties = jwtProperties;
    }

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {

        ServerHttpRequest request = exchange.getRequest();

        String paramToken = resolveParamToken(request);
        String headerToken = resolveHeaderToken(request);

        //有token情况 已经验证过
        if (StringUtils.hasLength(paramToken) || StringUtils.hasLength(headerToken)) {

            String token = StringUtils.hasLength(paramToken) ? SecurityConstant.HEAD + paramToken : headerToken;

            String userId = UserContextHolder.getUserId();
            String traceId = MDC.get(LogConstants.LOG_TRACE_ID);

            ServerHttpRequest serverHttpRequest = exchange.getRequest().mutate()
                    .headers(h -> h.add(SecurityConstant.HEADER_USER_ID, userId))
                    .headers(h -> h.add(SecurityConstant.HEADER_TRACE_ID, traceId))
                    .headers(h -> h.add(LogConstants.USER_ID_HEADER, userId))
                    .headers(h -> h.add(LogConstants.TRACE_ID_HEADER, traceId))
                    .headers(h -> h.add(SecurityConstant.TOKEN_HEADER, token))
                    .build();

            exchange = exchange.mutate().request(serverHttpRequest).build();
        }
        return chain.filter(exchange);
    }

    private String resolveHeaderToken(ServerHttpRequest request) {
        return request.getHeaders().getFirst(SecurityConstant.TOKEN_HEADER);
    }

    private String resolveParamToken(ServerHttpRequest request) {

        return request.getQueryParams().getFirst(SecurityConstant.TOKEN_PARAM);
    }
}
